package com.chuanke.ckfamily.service.common;

import com.chuanke.ckfamily.service.common.exception.LockException;
import com.chuanke.ckfamily.service.common.impl.RedisLockUtil;
import com.chuanke.ckfamily.service.common.impl.SynizedInvoker;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;

import java.io.Serializable;
import java.util.List;
import java.util.Set;

/**
 * 缓存服务接口
 * 
 * @author yc
 *
 */
public interface CacheService<K, V> extends Serializable {

	/**
	 * 所有保存在redis缓存中的前缀
	 *
	 */
	enum KEY_PREFIX {

		/**
		 * 用户key前缀
		 */
		user_,

		/**
		 * 用户分享
		 */
		user_share_time_,

		/**
		 * 家族key
		 */
		family_,

		/**
		 * 家族成员数量
		 */
		familyMnum_,

		/**
		 * 家族成员key
		 */
		familyMember_,
		
		
		/**
		 * 移动家族成员锁
		 */
		familyLock,

		equipment_,
		/**
		 * 红包
		 */
		packet_,

		/**
		 * 红包检查
		 */
		packetCheckup_,

		/**
		 * 红包领取锁
		 */
		packetPickup_,
		
		/**
		 * 红包发放锁
		 */
		packetSend_,

		config_,
		/**
		 * 用户资金集合的k
		 */
		bill_,
		/**
		 * 好友、粉丝备注
		 */
		remark_name_,

		/**
		 * 家族成员禁言
		 */
		member_mute_,
		
		/**
		 * 昨日家族排行
		 */
		familyRank_,

		/**
		 * freemarker模板
		 */
		freemarker_template_,

		/**
		 *
		 */
		family_day_incom_,

		/**
		 * 红包队列
		 */
		gain_packet_queue,

		/**订单队列*/
		bill_queue,

		/*家庭收入队列*/
		family_income_queue,

		/*USER DAYINCOME*/
		user_dayincome_,

		/*j*/
		dayIncome_,

		/** 家族资金明细*/
		family_finace,

		/*家族累计收益*/
		family_income,

		/** 红包资金明细*/
		packet_finace,

		/**红包金额队列*/
		packet_money_queue_,

		/**红包领取队列*/
		packet_gain_queue_,

		/**
		 * 红包领完标记
		 */
		packet_empty_,

		/*红包任务*/
		gain_packet_task_,

		/*家族收入任务*/
		family_income_task,

		friend_apply_,
		
		friend_delete_,
		
		friend_audit_apply_,

		/** face通过的ip*/
		ckeck_ip,

		user_relation_,
		
		special_relation_,
		
		send_family_msg_,

		move_user_;

	}

	/**
	 * 
	 * keyExists: 校验缓存中是否存在该key的数据 <br/>
	 * TODO(这里描述这个方法适用条件 – 可选).<br/>
	 * 
	 * @author yc
	 * @param key
	 * @return Boolean
	 * @since JDK 1.7
	 */
	Boolean keyExists(K key);

	/**
	 * 
	 * keyExists: 匹配缓存中是否已经存在k=x,v=x的数据了. <br/>
	 * 
	 * @author yc
	 * @param key
	 * @param value
	 * @return Boolean
	 * @since JDK 1.7
	 */
	Boolean keyExists(K key, V value);

	/**
	 * get:(获取数据). <br/>
	 * 
	 * @author yc
	 * @param key
	 * @return
	 * @since JDK 1.7
	 */
	V get(K key);

	/**
	 * set: 存储数据
	 * 
	 * @author yc
	 * @param key
	 * @param value
	 * @since JDK 1.7
	 */
	void set(K key, V value);

	/**
	 * 
	 * set:. 存储数据，带过期时间，以毫秒数为单位<br/>
	 * TODO.<br/>
	 * 
	 * @author yc
	 * @param key
	 * @param value
	 * @param expiredTime
	 * @since JDK 1.7
	 */
	void set(K key, V value, long expiredTime);

	/**
	 * 删除缓存数据 delete:. <br/>
	 * TODO.<br/>
	 * 
	 * @author yc
	 * @param key
	 * @since JDK 1.7
	 */
	void delete(K key);

	/**
	 * 
	 * deleteByPrex: 模糊删除以prex参数为前缀的key数据<br/>
	 * TODO.比如要删除user_开头的数据，请传入字符串user_ <br/>
	 * 但考虑到性能问题，可能存在大量数据时慎用
	 * 
	 * @author yc
	 * @param prex
	 * @since JDK 1.7
	 */
	@Deprecated
	void deleteByPrex(String prex);

	/**
	 * like查询条数
	 * 
	 * @param prex
	 * @return
	 */
	Integer getByPrexSize(String prex);

	/**
	 *
	 *
	 * @param prex
	 * @return
	 */
	Set<String> getKeysByPrex(String prex);

	/**
	 * 获取锁
	 *
	 * @param lockName
	 * @return
	 */
	RedisLockUtil getLock(String lockName) throws LockException;

	void geoAdd(K key, String lng, String lat, V value);

	void geoRemove(K key, V... value);

	List<GeoResult<GeoLocation<V>>> geoRadius(K key, String lng, String lat, Double radius);

	List<GeoResult<GeoLocation<V>>> geoRadiusByMember(K key, V value, Double radius);

	Long listSize(K key);

	List<V> getLists(K key, Long begin, Long end);

	V index(K key, int index);

	/**
	 * 移出并获取列表的最后一个元素
	 * 
	 * @param key
	 * @return
	 */
	V rightPop(K key);

	/**
	 * 移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
	 * 
	 * @param key
	 * @param timeout
	 * @return
	 */
	V rightPop(K key, long timeout);

	/**
	 * 将一个或多个值插入到列表头部
	 * 
	 * @param key
	 * @param value
	 */
	void leftPush(K key, V value);

	/**
	 * 加入批量
	 *
	 * @param key
	 * @param values
	 */
	void leftPushAll(K key, V... values);

	void flushDb();

	void invokeSynzied(K key, long timeOut, SynizedInvoker invoker);
}